package com.flyqiu.common.tools;

import com.flyqiu.common.fun.CollectionIterator;

import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;

/**
 * 提供了一系列用于处理集合和映射的工具方法。
 */
public class FlyQiuCollectionTools {

    /**
     * 检查集合是否为空。
     *
     * @param collection 集合
     * @return 如果集合为空或为null，则返回true；否则返回false
     */
    public static boolean isEmpty(Collection<?> collection) {
        return collection == null || collection.isEmpty();
    }

    /**
     * 检查集合是否不为空。
     *
     * @param collection 集合
     * @return 如果集合不为空且不为null，则返回true；否则返回false
     */
    public static boolean isNotEmpty(Collection<?> collection) {
        return !isEmpty(collection);
    }

    /**
     * 检查映射是否为空。
     *
     * @param map 映射
     * @return 如果映射为空或为null，则返回true；否则返回false
     */
    public static boolean isEmpty(Map<?, ?> map) {
        return map == null || map.isEmpty();
    }

    /**
     * 检查映射是否不为空。
     *
     * @param map 映射
     * @return 如果映射不为空且不为null，则返回true；否则返回false
     */
    public static boolean isNotEmpty(Map<?, ?> map) {
        return !isEmpty(map);
    }

    /**
     * 检查数组是否为空。
     *
     * @param array 数组
     * @param <T>   数组元素类型
     * @return 如果数组为空或长度为0，则返回true；否则返回false
     */
    public static <T> boolean isEmpty(T[] array) {
        return array == null || array.length < 1;
    }

    /**
     * 检查数组是否不为空。
     *
     * @param array 数组
     * @param <T>   数组元素类型
     * @return 如果数组不为空且长度大于0，则返回true；否则返回false
     */
    public static <T> boolean isNotEmpty(T[] array) {
        return !isEmpty(array);
    }

    /**
     * 迭代集合中的每个元素。
     *
     * @param collection 集合
     * @param consumer   消费者
     * @param <E>        集合元素类型
     */
    public static <E> void iterator(Collection<E> collection, Consumer<E> consumer) {
        if (isEmpty(collection)) {
            return;
        }
        for (E element : collection) {
            consumer.accept(element);
        }
    }

    /**
     * 迭代集合中的每个元素，并提供索引。
     *
     * @param collection 集合
     * @param consumer   消费者
     * @param <E>        集合元素类型
     */
    public static <E> void iteratorIndex(Collection<E> collection, CollectionIterator<E> consumer) {
        if (isEmpty(collection)) {
            return;
        }
        int index = 0;
        for (E element : collection) {
            consumer.accept(element, index++);
        }
    }

    /**
     * 迭代数组中的每个元素。
     *
     * @param array     数组
     * @param consumer  消费者
     * @param <E>       数组元素类型
     */
    public static <E> void iterator(E[] array, Consumer<E> consumer) {
        if (array == null || array.length < 1) {
            return;
        }
        for (E element : array) {
            consumer.accept(element);
        }
    }

    /**
     * 迭代映射中的每个键值对。
     *
     * @param map       映射
     * @param consumer  消费者
     * @param <K>       映射键类型
     * @param <V>       映射值类型
     */
    public static <K, V> void iterator(Map<K, V> map, BiConsumer<K, V> consumer) {
        if (isEmpty(map)) {
            return;
        }
        for (Map.Entry<K, V> entry : map.entrySet()) {
            consumer.accept(entry.getKey(), entry.getValue());
        }
    }

    /**
     * 将映射转换为列表。
     *
     * @param map       映射
     * @param consumer  转换函数
     * @param <K>       映射键类型
     * @param <V>       映射值类型
     * @param <R>       结果列表元素类型
     * @return 转换后的列表
     */
    public static <K, V, R> List<R> map(Map<K, V> map, BiFunction<K, V, R> consumer) {
        List<R> result = new ArrayList<>();
        if (isEmpty(map)) {
            return result;
        }
        for (Map.Entry<K, V> entry : map.entrySet()) {
            R apply = consumer.apply(entry.getKey(), entry.getValue());
            result.add(apply);
        }
        return result;
    }

    /**
     * 将集合转换为列表。
     *
     * @param collection 集合
     * @param mapper     转换函数
     * @param <T>        集合元素类型
     * @param <R>        结果列表元素类型
     * @return 转换后的列表
     */
    public static <T, R> List<R> map(Collection<T> collection, Function<? super T, ? extends R> mapper) {
        if (isEmpty(collection)) {
            return new ArrayList<>();
        }
        return collection.stream().map(mapper).collect(Collectors.toList());
    }

    /**
     * 查找集合中的元素。
     *
     * @param collection 集合
     * @param consumer   匹配函数
     * @param <E>        集合元素类型
     * @param <R>        结果元素类型
     * @return 匹配的元素列表
     */
    public static <E, R> List<R> find(Collection<E> collection, Function<E, R> consumer) {
        List<R> result = new ArrayList<>();
        if (isEmpty(collection)) {
            return result;
        }
        for (E element : collection) {
            R apply = consumer.apply(element);
            if (apply != null) {
                result.add(apply);
            }
        }
        return result;
    }

    /**
     * 查找集合中的第一个匹配元素。
     *
     * @param collection 集合
     * @param consumer   匹配函数
     * @param <E>        集合元素类型
     * @return 第一个匹配的元素，如果没有匹配则返回null
     */
    public static <E> E findOne(Collection<E> collection, Predicate<E> consumer) {
        if (isEmpty(collection)) {
            return null;
        }
        for (E element : collection) {
            if (consumer.test(element)) {
                return element;
            }
        }
        return null;
    }

    /**
     * 查找数组中的第一个匹配元素。
     *
     * @param array      数组
     * @param consumer   匹配函数
     * @param <E>        数组元素类型
     * @return 第一个匹配的元素，如果没有匹配则返回null
     */
    public static <E> E findOne(E[] array, Predicate<E> consumer) {
        if (array == null || array.length < 1) {
            return null;
        }
        for (E element : array) {
            if (consumer.test(element)) {
                return element;
            }
        }
        return null;
    }

    /**
     * 移除集合中符合条件的元素。
     *
     * @param collection 集合
     * @param function   匹配函数
     * @param <E>        集合元素类型
     */
    public static <E> void remove(Collection<E> collection, Predicate<E> function) {
        if (isEmpty(collection)) {
            return;
        }
        collection.removeIf(function);
    }

    /**
     * 根据分类器将列表分组。
     *
     * @param list       列表
     * @param classifier 分类器
     * @param <T>        列表元素类型
     * @param <K>        分组键类型
     * @return 分组后的映射
     */
    public static <T, K> Map<K, List<T>> group(List<T> list, Function<? super T, ? extends K> classifier) {
        if (isEmpty(list)) {
            return new HashMap<>();
        }
        return list.stream().collect(Collectors.groupingBy(classifier));
    }
}
